use std::sync::{Arc, Mutex};
use std::ffi::c_ulonglong;
use rayon::prelude::*;
pub struct SecondNum {
    v: Mutex<Vec<bool>>,
}

impl SecondNum {
    pub fn new() -> Arc<SecondNum> {
        Arc::new(SecondNum {
            v: Mutex::new(Vec::new()),
        })
    }
}

pub fn Get_num_size() -> u128 {
    let num_tmp = SecondNum::new();
    let sec_tmp: Vec<bool> = Vec::new();
    let bool_tmp: bool = false;
    let fsize: u128 =
        std::mem::size_of_val(&*num_tmp) as u128 + std::mem::size_of_val(&*sec_tmp) as u128
            + std::mem::size_of_val(&bool_tmp) as u128;
    return fsize;
}

pub fn Get_first_num(num: u128) -> Vec<Arc<SecondNum>> {
    (0..num)
        .into_par_iter()
        .map(|_| SecondNum::new())
        .collect()
}

pub fn Put_num(num1: u128, num2: u128, vec: &mut Vec<Arc<SecondNum>>) {
    let mut v = vec[num1 as usize].v.lock().unwrap();
    if num2 <= 0 {
        let num2 = 1;
    }
    if v.len() <= num2 as usize {
        v.resize(num2 as usize + 1, false);
    }
    v[num2 as usize] = true;
}

pub fn Remove_num(num1: u128, num2: u128, vec: &mut Vec<Arc<SecondNum>>) {
    if let Some(second_num) = vec.get(num1 as usize) {
        let mut v = second_num.v.lock().unwrap();
        if num2 <= 0 {
            let num2 = 1;
        }
        if num2 < v.len() as u128 {
            v[num2 as usize] = false;
        }
    }
}

pub fn Check_num(num1: u128, num2: u128, vec: &Vec<Arc<SecondNum>>) -> bool {
    loop {
        if num2 <= 0 {
            let num2 = 1;
        }
        if let Ok(v) = vec[num1 as usize].v.try_lock() {
            if num2 < v.len() as u128 {
                return v[num2 as usize];
            } else {
                return false;
            }
        }
    }
}

pub fn Get_size(num1: u128, vec: &Vec<Arc<SecondNum>>) -> u128 {
    if (num1 as usize) < vec.len() {
        let v = vec[num1 as usize].v.lock().unwrap();
        return v.len() as u128;
    } else {
        return 0;
    }
}

pub fn Del_num(vec: &mut Vec<Arc<SecondNum>>) {
    let mut temp_vec = Vec::new();

    for item in vec.iter() {
        if Arc::strong_count(item) > 1 {
            temp_vec.push(Arc::clone(item));
        }
    }

    vec.clear();
    vec.extend(temp_vec);
}

#[no_mangle]
pub extern "C" fn get_num_size() -> c_ulonglong {
    Get_num_size() as c_ulonglong
}

#[no_mangle]
pub extern "C" fn create_first_num(num: c_ulonglong) -> *mut Vec<Arc<SecondNum>> {
    let vec = Get_first_num(num as u128);
    Box::into_raw(Box::new(vec))
}

#[no_mangle]
pub extern "C" fn put_num(num1: c_ulonglong, num2: c_ulonglong, vec: *mut Vec<Arc<SecondNum>>) {
    let vec = unsafe { &mut *vec };
    Put_num(num1 as u128, num2 as u128, vec);
}

#[no_mangle]
pub extern "C" fn remove_num(num1: c_ulonglong, num2: c_ulonglong, vec: *mut Vec<Arc<SecondNum>>) {
    let vec = unsafe { &mut *vec };
    Remove_num(num1 as u128, num2 as u128, vec);
}

#[no_mangle]
pub extern "C" fn check_num(num1: c_ulonglong, num2: c_ulonglong, vec: *const Vec<Arc<SecondNum>>) -> bool {
    let vec = unsafe { &*vec };
    Check_num(num1 as u128, num2 as u128, vec)
}

#[no_mangle]
pub extern "C" fn get_size(num1: c_ulonglong, vec: *const Vec<Arc<SecondNum>>) -> c_ulonglong {
    let vec = unsafe { &*vec };
    return Get_size(num1 as u128, vec) as c_ulonglong;
}

#[no_mangle]
pub extern "C" fn del_num(vec: *mut Vec<Arc<SecondNum>>) {
    let vec = unsafe { &mut *vec };
    Del_num(vec);
}
